/**
 * 字段名转换工具
 * 用于处理数据库字段（snake_case）与前端接口（camelCase）之间的转换
 */

// 将snake_case转换为camelCase
export function snakeToCamel(str: string): string {
  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
}

// 将camelCase转换为snake_case
export function camelToSnake(str: string): string {
  return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
}

// 转换对象的所有键名从snake_case到camelCase
export function transformObjectToCamel<T = any>(obj: any): T {
  if (obj === null || obj === undefined) {
    return obj;
  }
  
  if (Array.isArray(obj)) {
    return obj.map(item => transformObjectToCamel(item)) as T;
  }
  
  if (typeof obj === 'object' && obj.constructor === Object) {
    const transformed: any = {};
    for (const [key, value] of Object.entries(obj)) {
      const camelKey = snakeToCamel(key);
      transformed[camelKey] = transformObjectToCamel(value);
    }
    return transformed;
  }
  
  return obj;
}

// 转换对象的所有键名从camelCase到snake_case
export function transformObjectToSnake<T = any>(obj: any): T {
  if (obj === null || obj === undefined) {
    return obj;
  }
  
  if (Array.isArray(obj)) {
    return obj.map(item => transformObjectToSnake(item)) as T;
  }
  
  if (typeof obj === 'object' && obj.constructor === Object) {
    const transformed: any = {};
    for (const [key, value] of Object.entries(obj)) {
      const snakeKey = camelToSnake(key);
      transformed[snakeKey] = transformObjectToSnake(value);
    }
    return transformed;
  }
  
  return obj;
}

// 字段映射配置类型
export interface FieldMapping {
  [camelCaseKey: string]: string; // snake_case_key
}

// 使用自定义映射转换对象（从数据库格式到前端格式）
export function transformWithMapping<T = any>(obj: any, mapping: FieldMapping): T {
  if (obj === null || obj === undefined) {
    return obj;
  }
  
  if (Array.isArray(obj)) {
    return obj.map(item => transformWithMapping(item, mapping)) as T;
  }
  
  if (typeof obj === 'object' && obj.constructor === Object) {
    const transformed: any = {};
    
    // 创建反向映射（snake_case -> camelCase）
    const reverseMapping: { [key: string]: string } = {};
    Object.entries(mapping).forEach(([camelKey, snakeKey]) => {
      reverseMapping[snakeKey] = camelKey;
    });
    
    for (const [key, value] of Object.entries(obj)) {
      // 如果有自定义映射，使用映射；否则使用自动转换
      const targetKey = reverseMapping[key] || snakeToCamel(key);
      transformed[targetKey] = transformWithMapping(value, mapping);
    }
    return transformed;
  }
  
  return obj;
}

// 使用自定义映射转换对象（从前端格式到数据库格式）
export function transformWithMappingReverse<T = any>(obj: any, mapping: FieldMapping): T {
  if (obj === null || obj === undefined) {
    return obj;
  }
  
  if (Array.isArray(obj)) {
    return obj.map(item => transformWithMappingReverse(item, mapping)) as T;
  }
  
  if (typeof obj === 'object' && obj.constructor === Object) {
    const transformed: any = {};
    
    for (const [key, value] of Object.entries(obj)) {
      // 如果有自定义映射，使用映射；否则使用自动转换
      const targetKey = mapping[key] || camelToSnake(key);
      transformed[targetKey] = transformWithMappingReverse(value, mapping);
    }
    return transformed;
  }
  
  return obj;
}

// 证券投资计划的字段映射配置
export const STOCK_PLAN_FIELD_MAPPING: FieldMapping = {
  id: 'id',
  userId: 'user_id',
  stockCode: 'stock_code',
  stockName: 'stock_name',
  currentPrice: 'current_price',
  maxDrawdown: 'max_drawdown',
  totalShares: 'total_shares',
  buyTimes: 'buy_times',
  strategy: 'strategy',
  averagePrice: 'average_price',
  totalAmount: 'total_amount',
  minLots: 'min_lots',
  lotSize: 'lot_size',
  stockType: 'stock_type',
  trackingIndex: 'tracking_index',
  managementFee: 'management_fee',
  riskLevel: 'risk_level',
  maxLoss: 'max_loss',
  createdAt: 'created_at',
  updatedAt: 'updated_at'
};

// 便捷方法：转换证券投资计划数据（数据库 -> 前端）
export function transformStockPlanFromDB<T = any>(data: any): T {
  return transformWithMapping(data, STOCK_PLAN_FIELD_MAPPING);
}

// 便捷方法：转换证券投资计划数据（前端 -> 数据库）
export function transformStockPlanToDB<T = any>(data: any): T {
  return transformWithMappingReverse(data, STOCK_PLAN_FIELD_MAPPING);
}

// 通用的数据转换装饰器工厂
export function createTransformDecorator<T = any>(
  mapping?: FieldMapping,
  direction: 'toCamel' | 'toSnake' | 'withMapping' | 'withMappingReverse' = 'toCamel'
) {
  return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    
    descriptor.value = async function(...args: any[]) {
      const result = await originalMethod.apply(this, args);
      
      if (result === null || result === undefined) {
        return result;
      }
      
      switch (direction) {
        case 'toCamel':
          return transformObjectToCamel<T>(result);
        case 'toSnake':
          return transformObjectToSnake<T>(result);
        case 'withMapping':
          return mapping ? transformWithMapping<T>(result, mapping) : transformObjectToCamel<T>(result);
        case 'withMappingReverse':
          return mapping ? transformWithMappingReverse<T>(result, mapping) : transformObjectToSnake<T>(result);
        default:
          return result;
      }
    };
    
    return descriptor;
  };
}

// 类型安全的转换函数
export class FieldTransformer {
  private mapping: FieldMapping;
  
  constructor(mapping: FieldMapping) {
    this.mapping = mapping;
  }
  
  // 从数据库格式转换到前端格式
  fromDB<T = any>(data: any): T {
    return transformWithMapping(data, this.mapping);
  }
  
  // 从前端格式转换到数据库格式
  toDB<T = any>(data: any): T {
    return transformWithMappingReverse(data, this.mapping);
  }
  
  // 批量转换
  fromDBBatch<T = any>(dataArray: any[]): T[] {
    return dataArray.map(item => this.fromDB<T>(item));
  }
  
  toBDBatch<T = any>(dataArray: any[]): T[] {
    return dataArray.map(item => this.toDB<T>(item));
  }
}

// 创建证券投资计划的转换器实例
export const stockPlanTransformer = new FieldTransformer(STOCK_PLAN_FIELD_MAPPING);

// 导出常用的转换函数
export {
  transformObjectToCamel as toCamel,
  transformObjectToSnake as toSnake,
  transformWithMapping as fromDBWithMapping,
  transformWithMappingReverse as toDBWithMapping
};